package com.hzaupj.sb.jfinal;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Ordering;
import com.google.common.collect.Table;
import com.hzaupj.sb.FoodParse;
import com.hzaupj.sb.HallParse;
import com.hzaupj.sb.json.JFood;
import com.hzaupj.sb.json.JShopCart;
import com.hzaupj.sb.util.BackTracking;
import com.hzaupj.sb.vo.Food;
import com.hzaupj.sb.vo.Hall;
import com.jfinal.core.Controller;
import jodd.bean.BeanCopy;
import jodd.util.StringUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

/**
 * IndexController
 */
public class SBController extends Controller {

	private FoodParse foodParse = new FoodParse();
	private HallParse hallParse = new HallParse();

	private static Map<String, Hall> hallMap; //key-hallId
	private static Table<String,String,Food> foodTable = HashBasedTable.create(); //key-hallId, foodId
	private static Map<String,Food> selectedFoodMap = new HashMap<String, Food>(); //key-hallId, foodId

	private static boolean canOrder = true;
	private static Map<Hall, Map<String, List<Food>>> reportMap;

	/**
	 * 餐厅列表
	 * @throws Exception
	 */
	public void hallList() throws Exception {
		createHallMap();

		setAttr("row", Math.ceil(hallMap.size()/4.0));
		setAttr("hallList", new ArrayList(hallMap.values()));
		render("/template/index.html");
	}

	/**
	 * 食物列表
	 * @throws Exception
	 */
	public void foodList() throws Exception {
		String hallId = getPara(0);
		String owner = getCookie("owner");
		String ownerNo = getCookie("ownerNo");
		// 获取foodTable
		createFoodTable(hallId);

		Hall hall = hallMap.get(hallId);
		if(owner == null){
			owner = "";
		}
		if(ownerNo == null){
			ownerNo = "";
		}


		double row = Math.ceil(foodTable.row(hallId).size()/3.0);

		Collection<Food> list = foodTable.row(hallId).values();
		setAttr("foodList", new ArrayList(list));
		setAttr("row", row);
		setAttr("hall", hall);
		setAttr("owner", URLDecoder.decode(owner, "UTF-8"));
		setAttr("ownerNo", URLDecoder.decode(ownerNo, "UTF-8"));

		render("/template/foodlist.html");
	}

	/**
	 * 提交
	 * @throws Exception
	 */
	public void submit() throws Exception {
		String hallId = getPara("hallId");
		String foodId = getPara("foodId");
		String no = getPara("no");
		String name = getPara("name");

		String result = "";
		if(!canOrder){
			result = "已经停止点单！";
			renderText(result);
			return;
		}

		if(StringUtil.isEmpty(no)){
			result = "请输入工号！";
			renderText(result);
			return;
		}

		if(StringUtil.isEmpty(name)){
			result = "请输入姓名！";
			renderText(result);
			return;
		}
		if(StringUtil.isEmpty(foodId)){
			result = "请选餐！";
			renderText(result);
			return;
		}

		Food selectedFood = foodTable.get(hallId, foodId);
		if(selectedFood == null) {
			result = "亲，找不到这个餐！";
			renderText(result);
			return;
		}

		Food newFood = new Food();
		BeanCopy.fromBean(selectedFood).toBean(newFood).copy();

		newFood.setOwner(name);
		newFood.setOwnerNo(no);
		newFood.setUuid(UUID.randomUUID().toString());
		selectedFoodMap.put(newFood.getUuid(), newFood);

		// 添加cookie
		if(!StringUtil.isEmpty(name) && !StringUtil.isEmpty(no)){
			setCookie("owner", URLEncoder.encode(name, "UTF-8"),5*365*24*60*60);
			setCookie("ownerNo", URLEncoder.encode(no, "UTF-8"), 5*365*24*60*60);
		}
		renderText("ok");
	}

	/**
	 * 点餐结果
	 * @throws Exception
	 */
	public void report() throws Exception {
		String ownerNo = getCookie("ownerNo");
		if(selectedFoodMap == null){
			renderText("没有任何人点餐！");
			return;
		}

		// selectdMap -- 谁点了什么吃的 （人 -- 食物）
		// calcMap -- 哪个餐厅点了哪些吃的（餐厅 -- 食物清单）
		Map<String, List<Food>> calcMap = getCalcMap(selectedFoodMap);

		// reportMap -- 哪个餐厅点了哪些吃的（餐厅 -- 拆分后的食物清单）
		reportMap = getReportMap(calcMap);

		// 统计折扣
		calDis(reportMap);

		setAttr("map", reportMap);
		setAttr("ownerNo", ownerNo == null ? "": ownerNo);
		render("/template/report.html");
	}

	/**
	 * 删除订餐
	 * @throws Exception
	 */
	public void delete() throws Exception {
		if(!canOrder){
			renderText("已经停止点单,不能删除！");
			return;
		}

		String uuid = getPara("uuid");
		selectedFoodMap.remove(uuid);
		renderText("删除成功");
	}

	/**
	 * 初始化
	 * @throws Exception
	 */
	public void init() throws Exception {
		hallMap = null;
		foodTable = HashBasedTable.create();
		selectedFoodMap = new HashMap<String, Food>();
		renderText("已经初始化清空");
	}

	/**
	 * 停止点餐
	 * @throws Exception
	 */
	public void stop() throws Exception {
		canOrder = false;
		renderText("停止点餐");
	}

	/**
	 * 开始点餐
	 * @throws Exception
	 */
	public void start() throws Exception {
		canOrder = true;
		renderText("恢复点餐");
	}

	public void pay() throws Exception {
		String key = getPara(0);
		String hallId = getPara(1);
		key = URLDecoder.decode(key, "UTF-8");
		if(StringUtil.isBlank(key)){
			renderText("找不到订单");
			return;
		}
		List<Food> foodList = getOrder(hallId, key);
		if(foodList == null || foodList.isEmpty()){
			renderText("找不到订单");
			return;
		}

		// 生成购物车信息
		JShopCart jShopCart = createShopCart(hallId, foodList);
		String url = Jsoup.connect("http://waimai.meituan.com/order/shoppingcart")
				.data("shop_cart", JSON.toJSONString(jShopCart))
				.post().baseUri();
		setAttr("location", url);
		render("/template/relocation.html");
	}

	private JShopCart createShopCart(String hallId, List<Food> foodList) {
		JShopCart jShopCart = new JShopCart();
		jShopCart.setPoi(Integer.valueOf(hallId));
		List<JFood> jfoodList = new ArrayList<JFood>();
		for(Food food : foodList){
			JFood jFood = new JFood();
			jFood.setSku(Integer.valueOf(food.getId()));
			jFood.setNum(1);
			jfoodList.add(jFood);
		}
		jShopCart.setFoods(jfoodList);
		return jShopCart;
	}

	private List<Food> getOrder(String hallId, String disInfo) {
		Set<Hall> keys = reportMap.keySet();
		Hall key = null;
		for(Hall hall : keys){
			if(hallId.equals(hall.getId())){
				key = hall;
				break;
			}
		}
		if(key == null){
			return null;
		}
		Map<String, List<Food>> map = reportMap.get(key);
		return map.get(disInfo);
	}

	private void createHallMap() throws IOException {
		hallMap = new HashMap<String, Hall>();

		List<Hall> hallList = hallParse.getHallList();
		for(Hall hall : hallList){
			hallMap.put(hall.getId(), hall);
		}
	}

	private void createFoodTable(String hallId) throws IOException {
		String url = String.format("http://waimai.meituan.com/restaurant/%s", hallId);
		List<Food> foodList = foodParse.getFoodList(hallId, url);
		for(Food food : foodList){
			foodTable.put(hallId, food.getId(), food);
		}
	}

	private Map<String, List<Food>> getCalcMap(Map<String,Food> selectedFoodMap) {
		Map<String, List<Food>> result = new HashMap<String, List<Food>>();
		Collection<Food> values = selectedFoodMap.values();
		for (Food food : values){
			List<Food> foodList = result.get(food.getHallId());
			if(foodList == null){
				foodList = new ArrayList<Food>();
			}
			foodList.add(food);
			result.put(food.getHallId(), foodList);
		}
		return result;
	}

	private Map<Hall, Map<String, List<Food>>> getReportMap(Map<String, List<Food>> calcMap) {
		Map<Hall, Map<String, List<Food>>> result = new HashMap<Hall, Map<String, List<Food>>>();
		BackTracking bt = new BackTracking();
		Set<String> keySet = calcMap.keySet();
		Iterator<String> it = keySet.iterator();
		while (it.hasNext()){
			String hallId = it.next();
			Hall hall = hallMap.get(hallId);
			Map<String, List<Food>> mapList = bt.calc(getDis(hall), calcMap.get(hallId));
			result.put(hall, mapList);
		}
		return result;
	}

	private List<String[]> getDis(Hall hall) {
		return sortList(hall.getDisList());
	}

	private void calDis(Map<Hall, Map<String, List<Food>>> reportMap) {
		Iterator<Hall> it = reportMap.keySet().iterator();
		while (it.hasNext()){
			Map<String, List<Food>> foodListMap = reportMap.get(it.next());
			Iterator<String> foodIt = foodListMap.keySet().iterator();
			while (foodIt.hasNext()){
				String disInfo = foodIt.next();
				String[] disInfos = disInfo.split("\\|");
				List<Food> foods = foodListMap.get(disInfo);
				double sumPrice = sum(foods);
				double reduceMoney = Integer.valueOf(disInfos[2]);
				reduceMoney = reduceMoney * 10;
				double disMoney = Integer.valueOf(disInfos[1]);
				disMoney = disMoney * 10;
				double dis = 1;
				if(sumPrice>=disMoney){
					dis = (sumPrice-reduceMoney)/sumPrice;
				}
				for(Food food : foods){
					double disPrice = new BigDecimal(food.getPrice()*dis).setScale(2, BigDecimal.ROUND_CEILING).doubleValue();
					food.setDisPrice(disPrice);
				}
			}
		}
	}

	private double sum(List<Food> list) {
		double sum = 0;
		for (Food food : list){
			sum = sum + food.getPrice();
		}
		return sum;
	}

	private List<String[]> sortList(List<String[]> srcList){
		Ordering<String[]> disOrdering = new Ordering<String[]>() {
			@Override
			public int compare( String[] left, String[] right) {
				return Integer.valueOf(right[1])-Integer.valueOf(left[1]);
			}
		};
		return disOrdering.immutableSortedCopy(srcList);
	}
}





